/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.playground.client.websockets.application;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.playground.client.websockets.entity.message.Action;
import com.playground.client.websockets.entity.message.request.PlayerRegistrationRequestMessage;
import com.playground.client.websockets.entity.message.request.RequestMessage;
import com.playground.client.websockets.entity.message.response.PlayerRegistrationResponseMessage;
import com.playground.client.websockets.entity.message.response.ResponseMessage;
import com.playground.client.websockets.socket.PlayerSocket;
import com.playground.client.websockets.util.JsonUtil;
import com.playground.core.entity.LoggedPlayer;
import com.playground.core.service.LoginService;
import com.sun.grizzly.websockets.ProtocolHandler;
import com.sun.grizzly.websockets.WebSocket;
import com.sun.grizzly.websockets.WebSocketApplication;
import com.sun.grizzly.websockets.WebSocketListener;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Tiago Peres
 */
public abstract class PlaygroundApplication extends WebSocketApplication {
    protected LoginService loginService;
    
    public PlaygroundApplication(LoginService loginService){
        this.loginService = loginService;
    }
    
    @Override
    public WebSocket createWebSocket(ProtocolHandler handler, WebSocketListener... listeners) {
        return new PlayerSocket(handler, listeners);
    }
    
    @Override
    public final void onMessage(WebSocket socket, String data){
        Logger.getLogger(PlaygroundApplication.class.getName()).log(Level.INFO, "MESSAGE RECEIVED");
        Logger.getLogger(PlaygroundApplication.class.getName()).log(Level.INFO, "MESSAGE: {0}", data);
        try{
            PlayerSocket psocket = (PlayerSocket) socket;
            try{
                RequestMessage msg = JsonUtil.getGson().fromJson(data, RequestMessage.class);
                System.out.println(msg.getAction());
                if (msg.getAction().equals(Action.registerPlayerToSocket)){
                    System.out.println("player registration requested.");
                    PlayerRegistrationRequestMessage regmsg = (PlayerRegistrationRequestMessage) msg;
                    System.out.println(regmsg.getPlayerId() + " :: " + regmsg.getPlayerKey());
                    registerPlayerToSocket(psocket, regmsg.getPlayerId(), regmsg.getPlayerKey());
                }
                else if (null != psocket.getPlayer()){
                    parseMessage(psocket, msg);
                } else{
                    ResponseMessage resp = new ResponseMessage();
                    resp.setAction(msg.getAction());
                    resp.setSuccess(false);
                    psocket.send(new Gson().toJson(resp, ResponseMessage.class));
                }
            } catch (JsonSyntaxException e){
                Logger.getLogger(PlaygroundApplication.class.getName()).log(Level.INFO, "MESSAGE IGNORED");
            }
        } catch(Exception e){
            e.printStackTrace();
        }
    }

    /**
     * Takes a RequestMessage and take an action based on its content. If an 
     * error is detected, false is returned. Otherwise, true is returned.
     * 
     * @param socket the socket the actions should be based on
     * @param message the message to be analized
     * @return true if the message is successfully parsed and executed, false 
     * otherwise
     */
    protected abstract boolean parseMessage(PlayerSocket socket, RequestMessage message);
    
    /**
     * Registers a player to a PlayerSocket. In case of success, a message 
     * containing a json with the player's Facebook Id, his status and the
     * games he can play is sent to the websocket. Otherwise, a message of
     * failure is sent.
     * 
     * After logging in, a key, related to the playerId, is created in the server.
     * The key and the playerId is sent to the recently connected user.
     * The user uses his id and the given key to identify himself to a websocket.
     * This method receives both parameters, verifies the key, retrieves the user
     * and set the retrieved player as the value of the attribute "player"
     * of the playerSocket.
     * 
     * @param socket the playerSocket requesting the register process
     * @param playerId the id of the player to be registered to the given 
     * playerSocket
     * @param key the key certifying the playerId corresponds to the player
     * making the request
     * @return true if the player was successfully registered, false otherwise
     */
    protected boolean registerPlayerToSocket(PlayerSocket socket, long playerId, String key) throws CloneNotSupportedException{
        System.out.println("entered");
        System.out.flush();
        LoggedPlayer lp = loginService.verifyLoggedPlayerKey(playerId, key);
        System.out.println("section 1 - ok");
        System.out.flush();
        PlayerRegistrationResponseMessage msg = new PlayerRegistrationResponseMessage();
        System.out.println("section 2 - ok");
        System.out.flush();
        if (null != lp){
            System.out.println("lp is not null");
            System.out.flush();
            socket.setPlayer(lp);
            LoggedPlayer copy = lp.clone();
            copy.setLastAction(null);
            copy.setRoom(null);
            msg.setSuccess(true);
            msg.setLoggedPlayer(copy);
        } else{
            System.out.println("lp is null");
            System.out.flush();
            msg.setSuccess(false);
        }
        System.out.println("section 3 - ok");
        System.out.flush();
        try{
        System.out.println(JsonUtil.getGson().toJson(msg, PlayerRegistrationResponseMessage.class));
        } catch (Exception e){e.printStackTrace();}
        System.out.println("section 4 - ok");
        System.out.flush();
        socket.send(JsonUtil.getGson().toJson(msg, PlayerRegistrationResponseMessage.class));
        System.out.println("section 5 - ok");
        System.out.flush();
        return(msg.isSuccess());
    }
}
